import pandas as pd
from pandas import DataFrame
import DataMiningtools as DMT


class DataPreprocessing (): #数据预处理工具
    OriginalData = None #存放原始数据
    WorkData = None #存放处理的数据
    Original_size = 0 #原始数据样本数
    Original_col = 0 #原始数据列数
    Original_a_num_arr = [] #原始数据每个属性取值个数
    DMT = None
    categorization = 0 #类别列
    c_num = 0 #类别取值数
    attribute_arr = [] #记录工作数据集使用的属性列
    att_num = 0
    chi2_val = pd.DataFrame() #记录卡方检验的结果


    def __init__(self,data) -> None:
        self.OriginalData = data
        self.Original_size = self.OriginalData.shape[0]
        self.Original_col = self.OriginalData.shape[1]
        self.DMT = DMT.DataMiningTools()
        self.Original_a_num_arr = self.DMT.AttributeMax(self.OriginalData)
        self.WorkData = pd.DataFrame()

    
    def CreateWorkData (self,attribute_arr): #从原始数据集中切出属性列
        self.attribute_arr = attribute_arr

        for i in range (0,len(attribute_arr)):
            self.WorkData[self.OriginalData.iloc[:,attribute_arr[i]].name] = \
            self.OriginalData.iloc[:,attribute_arr[i]]
            #抽取要分析的属性列构造工作集


    
    def Spearman (self,attribute_arr): #计算斯皮尔曼相关性系数
        self.CreateWorkData(attribute_arr)
        self.WorkData.corr(method='spearman').to_excel('./Spearman.xlsx',index=False)


    def Chi2_DataPrepare (self,categorization,attribute_arr,num): 
    #准备计算卡方需要的数据集
        self.categorization = categorization
        self.c_num = self.Original_a_num_arr[categorization] #确定类别以及类别取值个数

        self.CreateWorkData(attribute_arr)
        self.WorkData[self.OriginalData.iloc[:,categorization].name] = \
        self.OriginalData.iloc[:,categorization]
        work_c = self.WorkData.shape[1] - 1
        temp_data = None #存放不同类别的样本
        new_WorkData = pd.DataFrame()

        for c_val in range (0,self.c_num):
            temp_data = self.WorkData[self.WorkData.iloc[:,work_c] == c_val]
            temp_data  = self.DMT.RandSampling(num,temp_data)
            new_WorkData = pd.concat([new_WorkData,temp_data])
        
        self.WorkData = new_WorkData #构建工作集，确保每种类别样本数相同
    

    def Chi2 (self,categorization,attribute_arr,num): #计算卡方值
        self.Chi2_DataPrepare(categorization,attribute_arr,num)
        chi2_row = self.WorkData.iloc[0:1]
        work_c = self.WorkData.shape[1] - 1

        dict = {}

        for i in range (0,self.c_num):
                dict[i] = 0
        
        new_row = pd.DataFrame([dict])
        chi2 = new_row.iloc[:,:]

        self.att_num = len(self.attribute_arr)

        for i in range (0,2*self.att_num-1):
            chi2 = pd.concat([chi2,new_row])

        chi2 = chi2.reset_index()
        chi2 = chi2.iloc[:,1:self.c_num+1] #构造卡方结果表

        for i in range (0,self.att_num):#att_num个属性

            for j in range(0,2):#每个属性2种取值

                for k in range(0,self.c_num): #c_num种状态

                    chi2.iloc[i*2+j,k] = self.WorkData[(self.WorkData.iloc[:,i] == j) & \
                    (self.WorkData.iloc[:,work_c] == k)].count()[0]
                    #计算第i个属性的第j种取值为第k种状态的数目

        print (chi2)

        for i in range(0,self.att_num*2-1,2):
            t=chi2.iloc[i:i+2]
            
            c2 = 0
            count = [] #记录第i和i+1行第j列之和
            sum = 0 #记录第i行和第i+1行所有单元格之和
            rate = [] #记录count[j]/sum

            for j in range (0,self.c_num):
                count.append(t.iloc[:,j].sum())
                sum += count[j]
            
            for j in range (0,self.c_num):
                rate.append(count[j]/sum)

            
            for j in range (0,self.c_num):
                for k in range (0,2):
                    observed = t.iloc[k,j]
                    expected = 0

                    for l in range (0,self.c_num):
                        expected += t.iloc[k,l]
                    
                    expected *= rate[j]

                    c2 = c2+(observed-expected)**2/expected


            print ("属性",self.WorkData.iloc[:,int(i/2+1)-1].name,"卡方为",c2)
            chi2_row.iloc[0,int(i/2+1)-1] = c2
        
        self.chi2_val = pd.concat([self.chi2_val,chi2_row])
        print (self.chi2_val)


    def MultChi2 (self,categorization,attribute_arr,num,times): #进行多次卡方检验
        for i in range (0,times):
            self.WorkData = pd.DataFrame()
            self.Chi2 (categorization,attribute_arr,num)
        
        self.chi2_val.to_excel('./ChiSquareTestValue.xlsx',index=False)